﻿using System.Text;
using Elsa.Expressions.Contracts;
using Elsa.Extensions;
using Elsa.Workflows;
using Elsa.Workflows.Attributes;
using Elsa.Workflows.Memory;
using Elsa.Workflows.UIHints;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using T.FAS.Runtime.Base.Entity;
using T.FAS.Runtime.Expression.Entity;
using T.FAS.Runtime.MF.Activities.Extensions;
using T.FAS.Runtime.MF.Dao;
using T.FAS.Runtime.MF.Entity;
using T.FAS.Runtime.MF.SPI;
using T.ServiceComponent.Kernel.Service;

namespace T.FAS.Runtime.MF.Activities
{
    public class ActionExecuteActivity : FASCodeActivity<object?>
    {
        [Elsa.Workflows.Attributes.Input(Description = "Action的Code", UIHint = InputUIHints.SingleLine, Order = 1)]
        public string ActionName { get; set; }
        [Input(Description = "The cases to evaluate.", UIHint = "switch-editor", Order = 3)]
        public IList<BranchCondition> ParamList { get; set; }

     
        [Input(Description = "输出变量类型", Options = new[] { "void", "record", "list"}, DefaultValue = "void", UIHint = InputUIHints.DropDown, Order = 3)]

        public string OutputVarType { get; set; }

        public override List<Variable> ActivityOutputVariables { get { return OutputVariables != null ? OutputVariables.Values.ToList() : new List<Variable>(); } }
        /// <summary>
        /// 节点默认输出的变量
        /// </summary>
        //public List<Variable> OutputVariables { get; set; }
        public Dictionary<string, Variable> OutputVariables { get; set; }

        protected override async void Execute(ActivityExecutionContext context)
        {
            var scriptBuilder = new StringBuilder();

            try
            {
                scriptBuilder = await GetToExecuteScript(context);
                if (scriptBuilder.Length > 0)
                {
                    await ExecuteScript(context, scriptBuilder);
                }
            }
            catch (Exception ex)
            {
                await context.FaultAndComplete(ex, this);
            }
        }

        private async Task ExecuteScript(ActivityExecutionContext context,StringBuilder scriptBuilder)
        {
           // var expService = context.GetRequiredService<IFasExpService>();
            var factory = context.GetService<Func<string, IFasExpService>>();
            var expService = factory("publish");

            var extraParams= CallContext.GetData("WorkflowDebugParam");
            //调试模式
            if (extraParams != null)
            {
                expService = factory("debug");
            }

            var result = expService.Debug(scriptBuilder.ToString(), new Dictionary<string, object>(), extraParams!=null?(extraParams as Dictionary<string,string>):null);
            var outputInstanceValues = new Dictionary<string, object>() { };
            var id = context.Id;
            if (result != null)
            {
                //成功
                if (result.State == Expression.Entity.ResultState.Success)
                {
                  
                   
                    if (result.Result != null)
                    {
                      var resultValue = ProcessResultValue(result);
                        if (resultValue == null)
                        {
                            var exception = new Exception("DQ返回空值为空");

                            await context.FaultAndComplete(exception, this);
                        }

                        LogUtil.Log($"Action.result转换后的Value={JsonConvert.SerializeObject(resultValue)}");

                        //resultValue = result.Result;

                        context.SetResult(resultValue);
                       

                        foreach (var variableName in OutputVariables.Keys)
                        {
                            var variable = OutputVariables[variableName];
                            context.SetVariable(variable.Name, resultValue);

                            //向迭代返回值数组中赋值,这里会累计每次迭代的执行结果，返回到数组中
                            context.SetIterationVariableValue(variable.Name, resultValue);

                            //给输出参数赋值
                            outputInstanceValues[variableName] = resultValue;
                        }
                        OutputInstanceValues[context.Id] = outputInstanceValues;
                    }
                }
                else
                {
                    var exception = new Exception(result.ErrMsg);

                    await context.FaultAndComplete(exception, this);
                }
            }
        }
        private object? ProcessResultValue(ExprResult result)
        {
            object? resultValue = null;
            LogUtil.Log($"Action.result.Result.Type={result.Result.GetType()},result.Result as List<object>={result.Result as List<object>}");
            if (result.Result.GetType() == typeof(JArray))
            {
                resultValue = (result.Result as JArray).ToStructuredObjectArray();
            }
            else if (result.Result is TArray<TRecord>)
            {
                var resultJArrays = new JArray();
                var resultRecords = result.Result as TArray<TRecord>;
                foreach (var record in resultRecords)
                {
                    resultJArrays.Add(TRecord.ToJson(record));
                }
                resultValue = resultJArrays.ToStructuredObjectArray();
            }
            else if (result.Result is TArray<JObject>)
            {
                var resultJArrays = new JArray();
                var resultRecords = result.Result as TArray<JObject>;
                foreach (var record in resultRecords)
                {
                    resultJArrays.Add(record);
                }
                resultValue = resultJArrays.ToStructuredObjectArray();
            }
            else if (result.Result is JObject || result.Result is JToken)
            {
                resultValue = JArrayExtensions.ConvertJToken(result.Result as JToken);
            }
            if (result.Result is TRecord)
            {
                var record = result.Result as TRecord;
                resultValue = JArrayExtensions.ConvertJToken(TRecord.ToJson(record));
            }
            return resultValue;
        }

        private async Task<StringBuilder> GetToExecuteScript(ActivityExecutionContext context)
        {
            StringBuilder scriptBuilder=new StringBuilder();
          var inputInstanceValues = new Dictionary<string, object>();
            var expressionEvaluator = context.GetRequiredService<IExpressionEvaluator>();
            foreach (var param in ParamList)
            {
                var conditionValue = await expressionEvaluator.EvaluateAsync<object>(param.Condition, context.ExpressionExecutionContext);
                if (conditionValue == null)
                {
                    scriptBuilder.AppendLine($"let {param.Label}=null;");

                    //给入参实时数据赋值
                    inputInstanceValues[param.Label] = null;
                }
                else if (conditionValue.GetType().IsPrimitive == true)
                {
                    if (conditionValue.GetType() == typeof(char))
                    {
                        scriptBuilder.AppendLine($"let {param.Label}='{conditionValue}';");

                        //给入参实时数据赋值
                        inputInstanceValues[param.Label] = $"{conditionValue}";
                    }
                    else
                    {
                        scriptBuilder.AppendLine($"let {param.Label}={conditionValue};");

                        //给入参实时数据赋值
                        inputInstanceValues[param.Label] = conditionValue;
                    }


                }
                else
                {
                    if (conditionValue.GetType() == typeof(string))
                    {
                        scriptBuilder.AppendLine($"let {param.Label}='{conditionValue}';");
                        //给入参实时数据赋值
                        inputInstanceValues[param.Label] = $"{conditionValue}";
                    }
                    else
                    {
                        scriptBuilder.AppendLine($"let {param.Label}={JsonConvert.SerializeObject(conditionValue)};");
                        //给入参实时数据赋值
                        inputInstanceValues[param.Label] = $"{conditionValue}";
                    }
                }
               
            }
            this.InputInstanceValues[context.Id] = inputInstanceValues;
            var actionScript = $"Action.{ActionName}({string.Join(",", ParamList.Select(t => t.Label))})";
            if (OutputVarType == "list")
            {
                scriptBuilder.AppendLine($"{actionScript}.List;");
            }
            else if (OutputVarType == "record")
            {
                scriptBuilder.AppendLine($"{actionScript}.Record;");
            }
            else
            {
                scriptBuilder.AppendLine($"{actionScript};");
            }
            return scriptBuilder;
        }
    }
}
